﻿#define _CRT_SECURE_NO_WARNINGS 1
//指针2
//1、数组名的了解
//#include <stdio.h>
//int main()
//{
//	int arr[] = { 1,2,3 };
//	/*printf("&arr[0] = %p\n", &arr[0]);
//	printf("arr     = %p\n", arr);*/
//	//这里我们发现，&arr[0]与arr的地址是一样的，所以我们可以联想：arr == &arr[0]，也就是arr就是首元素的地址。
//
//	//当然，按照我们之前写过的代码，有一个特殊的情况：
//	int az = sizeof(arr) / sizeof(arr[0]);
//	//那就是这里的sizeof(arr)在之前不是算整个数组大小的吗？难道它也有猫腻。
//	printf("%d\n", sizeof(arr));	//通过输出我们看到了12，这是数组总字节的大小，所以我们认为：sizeof(数组名)，计算的是整个数组的⼤⼩，单位是字节
//
//	//当然，无独有偶，还有一种情况也暗藏玄机。
//	printf("&arr[0] = %p\n", &arr[0]);
//	printf("arr     = %p\n", arr);
//	printf("&arr     = %p\n", &arr);
//	//当我们打印时，发现它们的值还是相同的，那么我们再同时加1呢
//	printf("&arr[0]+1 = %p\n", &arr[0]+1);
//	printf("arr+1     = %p\n", arr+1);
//	printf("&arr+1     = %p\n", &arr+1);
//	//这时我们发现：&arr[0]+1和arr+1的输出值是一样的，并且互相比&arr[0]和arr差4个字节，但是&arr+1的输出值却与它们不一样，并且比&arr的输出值大12个字节，也就是这个数组的大小。
//	//所以我们总结：数组名是数组首元素的地址，除了：&数组名，取出的是整个数组的地址；sizeof(数组名)，计算的是整个数组的⼤⼩，单位是字节
//	return 0;
//}

//2、使用指针访问数组
//#include <stdio.h>
//int main()
//{
//	int arr[10] = { 0 };
//	int* pa = arr;
//	int i = 0;
//	int az = sizeof(arr) / sizeof(arr[0]);
//	for (i = 0; i < az; i++)
//	{
//		//当然，我们这里 pa+i == arr +i	,这里是表示从数组首元素地址开始，循环加i个字节到下一个数组元素。
//		scanf("%d", pa + i);	//这里通过指针变量来访问数组元素的地址，根据循环来逐个遍历输入数值
//	}
//	int j = 0;
//	for (j = 0; j < az; j++)
//	{
//		//这里也同理：*(pa+j) == arr[j] == pa[j] == *(arr+j) ,这里是因为 pa == arr
//		printf("%d ", *(pa + j));	//这里通过指针变量的解引用和循环遍历来获取数组的每个元素。这里需要注意是：由于+号的优先级小于*，所以建议加个括号避免报错
//	}
//	return 0;
//}

//3、一维数组传参的本质：就是将实参数组的首元素地址传到形参指针变量上。

//#include <stdio.h>
//int size(int* pa)	//然后我们这里也知道由于编译器的底层逻辑，它会将int arr[10]转换成int* pa
//{
//	//int bz = sizeof(arr) / sizeof(arr[0]);//所以我们认为这一表达式是不对的 //我们发现返回值是2，和我们预想的值10完全不符,所以我们知道传进来的是数组首元素的地址。
//	//根据我们所学的知识，我们知道了sizeof(arr)这里就是计算数组大小的，所以我们直接返回计算大小的值
//	return sizeof(pa);		//这里我们发现它是计算arr的类型大小，是根据arr在64位平台还是32位平台决定其数据类型大小从而返回值，像这里就返回了8
//}
//
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int az = sizeof(arr) / sizeof(arr[0]);
//	printf("%d\n", az);
//	printf("%d\n", size(arr));
//	return 0;
//}

//4、冒泡排序
//两两相邻的数进行比较。
//#include <stdio.h>
//void bubble(int arr[], int az)
//{
//	int i = 0;
//		
//	for (i = 0; i < az; i++)
//	{
//		int flag = 1;//假设它没进行交换，也就是有序状态
//		int j = 0;
//		for (j = 0; j < az-1-i; j++)	//冒泡排序有n个数要进行n-1次
//		{
//			if (arr[j] > arr[j+1])
//			{
//				int tmp = arr[j];
//				arr[j] = arr[j+1];
//				arr[j+1] = tmp;
//				flag = 0;	//进行了交换，那就是无序状态
//			}
//		}
//		if (flag == 1)
//		{
//			break;
//		}
//	}
//}
//
//int main()
//{
//	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
//	int az = sizeof(arr) / sizeof(arr[0]);
//	bubble(arr, az);
//	int b = 0;
//	for (b = 0; b < az; b++)
//	{
//		printf("%d ", arr[b]);
//	}
//	return 0;
//}

//5、二级指针：是指向一级指针变量
//#include <stdio.h>
//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	int** ppa = pa;
//	printf("%d\n", *pa);
//	printf("%d\n", *ppa);
//	return 0;
//}
//
//6、指针数组模拟⼆维数组
//这里我们先了解指针数组是什么：它是用来存放指针（地址）的数组
// 可以类比字符数组->存放字符的数组；整型数组->存放整型的数组

//这里需要根据数组元素的地址/存放数组的内存空间是连续的
//#include <stdio.h>
//int main()
//{
//	//先设置三个一维数组
//	int arr1[] = { 1,2,3,4,5 };
//	int arr2[] = { 2,3,4,5,6 };
//	int arr3[] = { 3,4,5,6,7 };
//	//这里运用了指针数组，用来存放指针，也就是各个数组的地址，这里我们知道了数组名就是数组首元素的地址。
//	int* pa[3] = { arr1,arr2,arr3 };
//	int i = 0;
//	int j = 0;
//	//这里是把指针看作行
//	for (i = 0; i < 3; i++)
//	{
//		//这里把数组元素看作列
//		for (j = 0; j < 5; j++)
//		{
//			printf("%d ", pa[i][j]);
//		}
//		printf("\n");
//	}
//	//综合起来就是指针数组循环遍历数组元素模拟成二维数组输出。
//	return 0;
//}